﻿using Microsoft.Extensions.DependencyInjection;
using ShardingCore;
using YunQue.Core.DB.DbOption;
using ShardingCore.Sharding.ReadWriteConfigurations;

namespace YunQue.Core.DB.ShardingCore
{
    /// <summary>
    /// ShardingCore扩展类,注册读写分离，分库分表等功能
    /// </summary>
    public static class ShardingCoreExtension
    {
        public static IServiceCollection AddDbContext(this IServiceCollection service, List<ShardingDbSource> shardingSources)
        {

            // 随机选择读库
            var random = new Random();
            string GetRandomReadConn(string groupName)
            {
                var readDbs = shardingSources
                    .Where(x => x.GroupName == groupName && !x.IsMaster)
                    .ToList();
                return readDbs[random.Next(readDbs.Count)].ConnectionString;
            }

            // 获取主库连接
            string GetMasterConn(string groupName)
            {
                return shardingSources
                    .First(x => x.GroupName == groupName && x.IsMaster)
                    .ConnectionString;
            }
            //获取默认主库连接
            string GetDefaultMasterConn()
            {
                return shardingSources
                    .First(x => x.IsMaster && x.IsDefault)
                    .ConnectionString;
            }
            service.AddShardingDbContext<YunQueBaseDbContext>()
                .UseRouteConfig(o =>
                {
                    // 分库分表路由配置
                    o.AddShardingTableRoute<TestTableShardRoute>();
                })
                .UseConfig(o =>
                {
                    o.AddDefaultDataSource("default", GetDefaultMasterConn());
                    // 批量注册所有读库
                    o.AddReadWriteSeparation(
                        sp =>
                        {
                            var dict = new Dictionary<string, IEnumerable<string>>();
                            foreach (var groupName in shardingSources.Select(s => s.GroupName).Distinct())
                            {
                                var readConns = shardingSources
                                    .Where(s => s.GroupName == groupName && !s.IsMaster)
                                    .Select(s => s.ConnectionString)
                                    .ToList();

                                dict[groupName] = readConns;
                            }
                            return dict;
                        },
                        ReadStrategyEnum.Loop, // 轮询读库
                        ReadWriteDefaultEnableBehavior.DefaultEnable, // 默认开启读写分离
                        10, // 默认优先级
                        ReadConnStringGetStrategyEnum.LatestFirstTime // 启动时优先用最新连接
                    );
                    // MySQL 配置
                    o.UseShardingQuery((conn, opt) =>
                    {
                        opt.UseMySql(conn, ServerVersion.AutoDetect(conn));
                    });
                    o.UseShardingTransaction((conn, opt) =>
                    {
                        opt.UseMySql(conn, ServerVersion.AutoDetect(conn.ConnectionString));
                    });


                });

            return service;
        }
    }
}
